package com.sinosoft.msf.base.supplier.controller;

import cn.hutool.core.exceptions.ValidateException;
import com.alibaba.fastjson.JSONException;
import com.sinosoft.msf.base.supplier.expection.BizException;
import com.sinosoft.msf.base.supplier.pojo.RestEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.HttpURLConnection;

/**
 * @author : lid
 * &#064;program  : m-starter
 * &#064;date  : 2022/8/14
 */
@SuppressWarnings("NullableProblems")
@Component
@ControllerAdvice("com.sinosoft.msf.base.web.supplier")
public class SupplierExceptionResolver{
    private static final Logger log = LoggerFactory.getLogger(SupplierExceptionResolver.class);


    /**
     * 处理自定义的异常
     */
    @ExceptionHandler({BizException.class})
    public void resolveBizException(HttpServletResponse response, Object arg2, Exception ex) {
        log.info("业务校验异常:{}", ex.getMessage());
        this.writeJsonResponse(response, HttpURLConnection.HTTP_OK, RestEntity.error(ex.getMessage()).toString());
    }
    /**
     * 处理hutool工具的参数校验异常
     */
    @ExceptionHandler({ValidateException.class})
    public void resolveVaiException(HttpServletResponse response, Object arg2, Exception ex) {
        log.info("业务校验异常:{}", ex.getMessage());
        this.writeJsonResponse(response, HttpURLConnection.HTTP_OK, RestEntity.error(ex.getMessage()).toString());
    }

    /**
     * 处理使用入参时 参数绑定异常
     */
//    @ExceptionHandler({BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
    @ExceptionHandler({BindException.class, MethodArgumentNotValidException.class})
    public void resolveParamException(HttpServletResponse response, Object arg2, Exception ex) {
        log.info("参数校验异常:{}", ex.getMessage());
        String msg = "";
        if (ex instanceof MethodArgumentNotValidException) {
            BindingResult bindingResult = ((MethodArgumentNotValidException) ex).getBindingResult();
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                msg = fieldError.getDefaultMessage();
            }
        } else if (ex instanceof BindException) {
            FieldError fieldError = ((BindException) ex).getFieldError();
            if (fieldError != null) {
                msg = fieldError.getDefaultMessage();
            }
        }
        this.writeJsonResponse(response, HttpURLConnection.HTTP_OK, RestEntity.error(msg).toString());
    }
    @ExceptionHandler(Exception.class)
    public void resolveException(HttpServletRequest request,
                                 HttpServletResponse response, Object arg2, Exception ex) {
        log.error("Controller-500-Exception-[{}]", request.getRequestURI());
        log.error("出现异常", ex);

        RestEntity rest = RestEntity.error();
        if (ex instanceof JSONException) {
            rest.setMsg("参数格式不正确！");
        } else if (ex instanceof ValidateException) {
            rest.setMsg(ex.getMessage());
        } else {
            rest.setMsg("未知错误");
        }

        this.writeJsonResponse(response, HttpURLConnection.HTTP_INTERNAL_ERROR, rest.toString());

    }

    public void writeJsonResponse(HttpServletResponse response, String resBody) {
        this.writeJsonResponse(response, 200, resBody);
    }

    public void writeJsonResponse(HttpServletResponse response, int responseStatus, String resBody) {
        try {
            response.setContentType("application/json");
            response.setStatus(responseStatus);
            response.setCharacterEncoding("UTF-8");
            final PrintWriter out = response.getWriter();
            out.print(resBody);
            out.flush();
        } catch (IOException e) {
            throw new IllegalStateException("Write OAuthResponse error", e);
        }
    }
}
